#include <fmt/core.h>
#include <zip.h>
#include <filesystem>
#include <fstream>
#include <memory>
#include <vector>
#include <string_view>

namespace superunzip::utils
{
    bool extractZip(const std::string &zip_path, const std::string &out_dir)
    {
        namespace fs = std::filesystem;

        try
        {
            // 创建输出目录（递归创建）
            fs::create_directories(out_dir);

            // 打开ZIP文件
            int err = 0;
            std::unique_ptr<zip_t, decltype(&zip_close)> archive(
                zip_open(zip_path.c_str(), ZIP_RDONLY, &err),
                &zip_close);

            if (!archive)
            {
                fmt::println(stderr, "无法打开文件 {}，错误码：{}", zip_path, err);
                return false;
            }

            // 获取文件数量
            const zip_int64_t num_entries = zip_get_num_entries(archive.get(), 0);
            std::vector<char> buffer(1 << 20); // 1MB缓冲区

            // 解压所有文件
            for (zip_int64_t i = 0; i < num_entries; ++i)
            {
                // 获取文件名
                const char *name = zip_get_name(archive.get(), i, 0);
                if (!name || !*name)
                    continue; // 跳过空名称

                // 判断是否为目录（更安全的实现）
                const std::string_view name_view(name);
                const bool is_dir = !name_view.empty() && name_view.back() == '/';

                // 构建完整输出路径
                fs::path out_path = fs::path(out_dir) / name;
                fmt::println("处理: {}", out_path.string());

                // 处理目录
                if (is_dir)
                {
                    fs::create_directories(out_path); // 确保多级目录创建
                    continue;
                }

                // 确保父目录存在（某些ZIP可能不包含目录条目）
                fs::create_directories(out_path.parent_path());

                // 打开zip文件条目
                std::unique_ptr<zip_file_t, decltype(&zip_fclose)> file(
                    zip_fopen_index(archive.get(), i, 0),
                    &zip_fclose);
                if (!file)
                {
                    fmt::println(stderr, "无法打开zip条目: {}", name);
                    continue;
                }

                // 写入文件（RAII管理）
                std::ofstream out_file(out_path, std::ios::binary);
                if (!out_file)
                {
                    fmt::println(stderr, "无法创建文件: {}", out_path.string());
                    continue;
                }

                // 分块读取写入（更高效的错误处理）
                zip_int64_t n;
                while ((n = zip_fread(file.get(), buffer.data(), buffer.size())) > 0)
                {
                    if (!out_file.write(buffer.data(), n))
                    {
                        fmt::println(stderr, "写入文件失败: {}", out_path.string());
                        break;
                    }
                }
            }
            return true;
        }
        catch (const std::exception &e)
        {
            fmt::println(stderr, "解压过程中发生错误: {}", e.what());
            return false;
        }
    }
}
